﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Mail;
using System.IO;

namespace Alex.Library.Net.Mail {
    /// <summary>
    /// SMTP邮件
    /// </summary>
    public class SmtpMail : IMail {
        private SmtpClient client;
        private MailMessage msg;
        private long maxAttachmentSize = 10485760; //10M
        private string[ ] attachmentFileExts;
        private List<string> attachmentFileNames;
        public SmtpMail () {
            client = new SmtpClient ();
            msg = new MailMessage ();
            msg.Subject = "New Mail";
            msg.To.Clear ();
            msg.CC.Clear ();
            msg.Attachments.Clear ();
            attachmentFileNames = new List<string> ();
        }

        public IMail SetHost ( string address ) {
            client.Host = address;
            return this;
        }

        public IMail SetPort ( int port ) {
            client.Port = port;
            return this;
        }

        public IMail SetCredential ( string userName, string password ) {
            client.UseDefaultCredentials = false;

            if ( userName.Contains ( @"\" ) ) {
                string[ ] s = userName.Split ( '\\' );
                string domain = s[ 0 ];
                string uname = s[ 1 ];
                client.Credentials = new NetworkCredential ( uname, password, domain );
            } else {
                client.Credentials = new NetworkCredential ( userName, password );
            }
            return this;
        }

        public IMail SetSender ( string senderAddress ) {
            msg.From = new MailAddress ( senderAddress );
            return this;
        }

        public IMail AddRecipient ( string recipientAddress ) {
            msg.To.Add ( new MailAddress ( recipientAddress ) );
            return this;
        }

        public IMail AddCc ( string ccAddress ) {
            msg.CC.Add ( new MailAddress ( ccAddress ) );
            return this;
        }

        public IMail SetSubject ( string subject ) {
            msg.Subject = subject;            
            return this;
        }

        public IMail SetSubjectEncoding ( Encoding encoding ) {
            msg.SubjectEncoding = encoding;
            return this;
        }

        public IMail SetBody ( string body, bool isHTML = true ) {
            msg.Body = body;            
            msg.IsBodyHtml = isHTML;
            return this;
        }

        public IMail SetBodyEncoding ( Encoding encoding ) {
            msg.BodyEncoding = encoding;
            return this;
        }

        public IMail SetPriority ( MyMailPriority priority ) {
            switch ( priority ) {
                case MyMailPriority.High:
                    msg.Priority = MailPriority.High;
                    break;
                case MyMailPriority.Low:
                    msg.Priority = MailPriority.Low;
                    break;
                case MyMailPriority.Normal:
                    msg.Priority = MailPriority.Normal;
                    break;
            }
            
            return this;
        }

        public IMail SetSslEnabled ( bool enabled ) {
            client.EnableSsl = enabled;
            return this;
        }

        public IMail SetAttachmentMaxSize ( long maxSize ) {
            this.maxAttachmentSize = maxSize;
            return this;
        }

        public IMail SetAttachmentFileExts ( string[ ] fileExts ) {
            this.attachmentFileExts = fileExts;
            return this;
        }        

        public IMail AddAttachment ( string filename ) {
            msg.Attachments.Add ( new Attachment ( filename ) );
            this.attachmentFileNames.Add ( filename );
            return this;
        }

        public IMail Send () {
            try {
                Valid ();
                client.DeliveryMethod = SmtpDeliveryMethod.Network;
                client.Send ( msg );
                return this;
            } catch {
                throw;
            }
        }        

        private void Valid () {
            if ( msg.From == null) {
                throw new Exception ( "缺少发件人地址." );
            }
            if ( msg.To == null || msg.To.Count == 0 ) {
                throw new Exception ( "缺少收件人地址." );
            }
            if ( msg.Attachments != null && msg.Attachments.Count > 0 ) {
                long totalSize = 0;
                foreach ( Attachment attachment in msg.Attachments ) {
                    totalSize += attachment.ContentStream.Length;
                }
                int maxSize = ( int ) ( this.maxAttachmentSize / 1024 / 1024 );
                if ( totalSize > this.maxAttachmentSize ) {
                    throw new Exception ( "附件大小不能超过" + maxSize + "M." );
                }
                if ( this.attachmentFileExts != null && this.attachmentFileExts.Length > 0 ) {
                    string fileExt = "";
                    foreach ( string filename in this.attachmentFileNames ) {
                        fileExt = Path.GetExtension ( filename );
                        if ( !this.attachmentFileExts.Contains ( fileExt,
                            StringComparer.OrdinalIgnoreCase ) ) {
                            throw new Exception ( "只允许上传" + String.Join ( "|", this.attachmentFileExts ) + "的格式附件." );
                        }
                    }
                }
            }
        }
    }
}
